﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverlightClientLibrary.Messages;

namespace SilverlightClientLibrary.Clients
{
    public class TcpCommunicator
    {
        #region Private Members

        private TcpSocketController _littleSocket;
        private TcpSocketController _bigSocket;

        #endregion

        #region Events

        public event Action ConnectedEvent;
        public event Action DroppedEvent;
        public event Action<NewClientMessage> ClientAdded;
        public event Action<ClientRemovedMessage> ClientRemoved;
        public event Action<NameChangeMessage> NewNameReceived;
        public event Action<PointMessage> PointDataReceived;
        public event Action<ChatMessage> ChatMessageReceived;

        #endregion

        #region Properties

        public int LittleEnqueuedMessages { get { return _littleSocket.EnqueuedBuffers; } }
        public int BigEnqueuedMessage { get { return _bigSocket.EnqueuedBuffers; } }
        public bool IsConnected { get { return _littleSocket.IsConnected && _bigSocket.IsConnected; } }

        #endregion

        #region Constructors

        public TcpCommunicator(Application app)
        {
            _littleSocket = new TcpSocketController(app, 16, 4502);
            _littleSocket.Connected += this.LittleSocketConnected;
            _littleSocket.Dropped += this.Dropped;
            _littleSocket.DataReceived += this.DecodeMessage;
            _bigSocket = new TcpSocketController(app, 1024, 4503);
            _bigSocket.Connected += this.BigSocketConnected;
            _bigSocket.Dropped += this.Dropped;
            _bigSocket.DataReceived += this.DecodeMessage;
        }

        #endregion

        #region Public Methods

        public void Connect()
        {
            _littleSocket.Connect();
            _bigSocket.Connect();
        }

        public void EnqueueMessage(Message m)
        {
            if (m.BufferSize == 16)
                _littleSocket.EnqueueBuffer(m.Encode());
            else
                _bigSocket.EnqueueBuffer(m.Encode());
        }

        #endregion

        #region Private Helpers

        private void LittleSocketConnected()
        {
            if (_littleSocket.IsConnected && _bigSocket.IsConnected && ConnectedEvent != null) ConnectedEvent();
        }

        private void BigSocketConnected()
        {
            if (_littleSocket.IsConnected && _bigSocket.IsConnected && ConnectedEvent != null) ConnectedEvent();
        }

        private void Dropped()
        {
            if (DroppedEvent != null) DroppedEvent();
        }

        private void DecodeMessage(byte[] buffer)
        {
            MessageId messageType = (MessageId)buffer[0];

            switch (messageType)
            {
                case MessageId.NewClientMessage:
                    //_littleSocket.FlushBuffer();
                    //_bigSocket.FlushBuffer();
                    NewClientMessage ncm1 = new NewClientMessage(0, buffer.Length);
                    ncm1.DecodeIdOfSender(buffer);
                    ncm1.Decode(buffer);
                    if (ClientAdded != null) ClientAdded(ncm1);
                    break;
                case MessageId.ClientRemovedMessage:
                    ClientRemovedMessage crm = new ClientRemovedMessage(0);
                    crm.DecodeIdOfSender(buffer);
                    crm.Decode(buffer);
                    if (ClientRemoved != null) ClientRemoved(crm);
                    break;
                case MessageId.NameChangeMessage:
                    NameChangeMessage ncm2 = new NameChangeMessage("");
                    ncm2.DecodeIdOfSender(buffer);
                    ncm2.Decode(buffer);
                    NewNameReceived(ncm2);
                    break;
                case MessageId.PointMessage:
                    PointMessage pm = new PointMessage(new Point());
                    pm.DecodeIdOfSender(buffer);
                    pm.Decode(buffer);
                    PointDataReceived(pm);
                    break;
                case MessageId.ChatMessage:
                    ChatMessage cm = new ChatMessage("");
                    cm.DecodeIdOfSender(buffer);
                    cm.Decode(buffer);
                    ChatMessageReceived(cm);
                    break;
            }
        }

        #endregion
    }
}